﻿using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Xml.Linq;
using NetSurveillance.WebApp.DataServices.Models;

namespace NetSurveillance.WebApp.Utilities
{
    public class ActionXmlUtility
    {
        private static ActionXmlUtility _instance;
        public static ActionXmlUtility Instance
        {
            get { return _instance ?? (_instance = new ActionXmlUtility()); }
        }

        public XElement GeneratorActionXml(XElement rootEle, params XElement[] childEles)
        {
            foreach (var childEle in childEles)
            {
                rootEle.Add(childEle);
            }
            return rootEle;
        }

        /// <summary>
        /// 创建action命令根节点
        /// </summary>
        /// <returns>action命令根节点</returns>
        public XElement CreateActionRootElement()
        {
            var rootXml = new XElement("root");

            return rootXml;
        }

        /// <summary>
        /// 创建案件和任务节点
        /// </summary>
        /// <param name="caseId">案件id</param>
        /// <param name="taskId">任务id</param>
        /// <returns>案件和任务节点</returns>
        public XElement CreateInfoElement(long caseId, long taskId)
        {
            var infoEle = new XElement("info",
                                       new XAttribute("caseid", caseId),
                                       new XAttribute("taskid", taskId));
            return infoEle;
        }

        /// <summary>
        /// 创建线路类型和线路模式节点(设置向导第一步)
        /// </summary>
        /// <param name="lineType">线路类型</param>
        /// <param name="lineMethod">线路模式</param>
        /// <param name="pcapPath">导入包的路径</param>
        /// <returns>线路类型和线路模式节点</returns>
        public XElement CreateLineElement(string lineType, string lineMethod, string pcapPath)
        {
            var lineEle = new XElement("line");
            var lineTypeEle = new XElement("type") { Value = lineType };
            var lineMethodEle = new XElement("method") { Value = lineMethod };
            lineEle.Add(lineTypeEle);
            lineEle.Add(lineMethodEle);
            lineEle.Add(new XElement("pcap") {Value = string.IsNullOrWhiteSpace(pcapPath) ? string.Empty : pcapPath});
            return lineEle;
        }

        /// <summary>
        /// 关键字节点(设置向导最后一步)
        /// </summary>
        /// <param name="keywords">关键字集合</param>
        /// <returns>关键字节点</returns>
        public XElement CreateKeywordsElement(IEnumerable<Keyword> keywords)
        {
            var keywordsEle = new XElement("keyword");
            foreach (var keyword in keywords)
            {
                var keywordEle = new XElement("clue");
                keywordEle.Add(new XAttribute("id", keyword.Id.ToString(CultureInfo.InvariantCulture)));
                keywordEle.Add(new XAttribute("keyword", keyword.KeywordName));
                keywordEle.Add(new XAttribute("protocol", keyword.Protocols));
                keywordEle.Add(new XAttribute("fields", keyword.Fields));
                keywordEle.Add(new XAttribute("warnning", keyword.IsWarning == true ? 1 : 0));
                keywordsEle.Add(keywordEle);
            }
            return keywordsEle;
        }

        /// <summary>
        /// 创建(设置)任务运行状态节点
        /// </summary>
        /// <param name="taskStatus">需要设置任务的状态值</param>
        /// <returns>任务运行状态节点</returns>
        public XElement CreateSetActionStatusElement(TaskStatusType taskStatus)
        {
            string taskStatusStr;
            switch (taskStatus)
            {
                case TaskStatusType.Running:
                    taskStatusStr = "start";
                    break;
                case TaskStatusType.Suspend:
                    taskStatusStr = "pause";
                    break;
                default:
                    taskStatusStr = "stop";
                    break;
            }
            var actionEle = new XElement("action") { Value = taskStatusStr };
            return actionEle;
        }

        /// <summary>
        /// 创建主机扫描节点
        /// </summary>
        /// <param name="interactiveId">交互id</param>
        /// <param name="startIp">起始ip</param>
        /// <param name="endIp">终止ip</param>
        /// <returns>主机扫描节点</returns>
        public XElement CreateHostScanXml(long interactiveId, string startIp, string endIp)
        {
            var interactiveEle = CreateInteractiveElement(interactiveId, "scanip");
            var scanipEle = new XElement("scanip", new XAttribute("action", "start"),
                                         new XElement("start", startIp),
                                         new XElement("end", endIp));
            var rootXml = GeneratorActionXml(CreateActionRootElement(), interactiveEle, scanipEle);
            return rootXml;
        }

        /// <summary>
        /// 创建停止扫描节点
        /// </summary>
        /// <returns>停止扫描节点</returns>
        public XElement CreateStopHostScanElement()
        {
            var scanIpEle = new XElement("scanip", new XAttribute("action", "stop"));
            return GeneratorActionXml(CreateActionRootElement(), scanIpEle);
        }

        /// <summary>
        /// 创建获取监控机ip节点
        /// </summary>
        /// <returns>获取监控机ip节点</returns>
        public XElement CreateLocalIpElement()
        {
            var localIpEle = new XElement("localip") { Value = "get" };
            return localIpEle;
        }

        /// <summary>
        /// 创建设置监控机ip节点
        /// </summary>
        /// <param name="ipSetting">监控机ip信息</param>
        /// <returns>设置监控机ip节点</returns>
        public XElement CreateSetServerIpElement(IpSetting ipSetting)
        {
            if (ipSetting == null)
                return null;
            var serverIpElement = new XElement("monitor",
                                               new XAttribute("devicename", ipSetting.DeviceName),
                                               new XAttribute("ip", ipSetting.Ip),
                                               new XAttribute("mask", ipSetting.SubnetMask),
                                               new XAttribute("gateway", ipSetting.Gateway));
            return serverIpElement;
        }

        /// <summary>
        /// 创建木马植入信息节点
        /// </summary>
        /// <param name="isAutoMonitorHost">是否自动监控新主机</param>
        /// <param name="isAutoWarning">是否自动报警</param>
        /// <param name="attackCount">攻击次数</param>
        /// <param name="hosts">主机</param>
        /// <param name="virusEmbedRules">规则</param>
        /// <returns>木马植入信息节点</returns>
        public XElement CreateVirusEmbedInfoElement(bool? isAutoMonitorHost, bool? isAutoWarning,
                                                    int? attackCount, IList<Host> hosts,
                                                    IList<VirusEmbedRule> virusEmbedRules)
        {
            var veInfoElement = new XElement("trojan_horse");

            string autoNewStr = (isAutoMonitorHost.HasValue && isAutoMonitorHost.Value) ? "1" : "0";
            veInfoElement.Add(new XElement("autonew") { Value = autoNewStr });
            string autoWarningStr = (isAutoWarning.HasValue && isAutoWarning.Value) ? "1" : "0";
            veInfoElement.Add(new XElement("autowarn") { Value = autoWarningStr });
            if (hosts != null && hosts.Any())
            {
                foreach (var host in hosts)
                {
                    var hostEle = new XElement("host", new XAttribute("id", host.Id),
                                               new XAttribute("ip", host.IP), new XAttribute("mac", host.Mac));
                    veInfoElement.Add(hostEle);
                }
            }
            if (virusEmbedRules != null && virusEmbedRules.Any())
            {
                var veRuleEles = new XElement("rules");
                veRuleEles.Add(new XAttribute("attack_count", attackCount.HasValue ? attackCount.Value : 0));
                foreach (var veRule in virusEmbedRules)
                {
                    var veRuleEle = new XElement("rule", new XAttribute("id", veRule.Id),
                                                 new XAttribute("name", veRule.RuleName));
                    if (veRule.IsRedirectPage)
                        veRuleEle.Add(new XAttribute("page_origin", veRule.OriginPage),
                                      new XAttribute("page_target", veRule.TargetPage));
                    if (veRule.IsRedirectFile)
                        veRuleEle.Add(new XAttribute("file_origin", veRule.OriginFileName),
                                      new XAttribute("file_target", veRule.TargetFileName));
                    if (veRule.IsRedirectAfterInstall)
                        veRuleEle.Add(new XAttribute("succ_condition", veRule.RedirectUrlAfterInstall));
                    veRuleEles.Add(veRuleEle);
                }
                veInfoElement.Add(veRuleEles);
            }
            return veInfoElement;
        }

        /// <summary>
        /// 创建交互节点
        /// </summary>
        /// <param name="interactiveId">交互id</param>
        /// <param name="typeStr">交互类型</param>
        /// <returns>交互节点</returns>
        public XElement CreateInteractiveElement(long interactiveId, string typeStr)
        {
            var interactiveEle = new XElement("interactive",
                                                   new XAttribute("id", interactiveId),
                                                   new XAttribute("type", typeStr));
            return interactiveEle;
        }

        public XElement CreateQQMonitorElement(IList<Host> hosts, IList<QQPassword> qqPasswords, bool? isAutoMonitorHost,
                                               bool? isAutoWarning)
        {
            var qqMonitorEle = new XElement("qqmonitor");
            string autoNewStr = (isAutoMonitorHost.HasValue && isAutoMonitorHost.Value) ? "1" : "0";
            qqMonitorEle.Add(new XElement("autonew") { Value = autoNewStr });
            string autoWarnStr = isAutoWarning.HasValue && isAutoWarning.Value ? "1" : "0";
            qqMonitorEle.Add(new XElement("autowarn") { Value = autoWarnStr });
            if (hosts != null && hosts.Any())
            {
                foreach (var host in hosts)
                {
                    var hostEle = new XElement("host", new XAttribute("id", host.Id),
                                               new XAttribute("ip", host.IP), new XAttribute("mac", host.Mac));
                    qqMonitorEle.Add(hostEle);
                }
            }
            if (qqPasswords != null && qqPasswords.Any())
            {
                foreach (var qqPass in qqPasswords)
                {
                    var qqPassEle = new XElement("qq",
                                                 new XAttribute("id", qqPass.Id),
                                                 new XAttribute("num", qqPass.Account),
                                                 new XAttribute("pass", qqPass.Password));
                    qqMonitorEle.Add(qqPassEle);
                }
            }
            return qqMonitorEle;
        }

        public XElement CreateWhiteListElement(IList<WhiteList> whiteLists)
        {
            var wlEle = new XElement("white");
            if (whiteLists != null && whiteLists.Any())
            {
                foreach (var wlGroup in whiteLists.GroupBy(p => p.Type))
                {
                    XElement domainEles = new XElement("urllist"),
                             macEles = new XElement("maclist"),
                             portEles = new XElement("portlist"),
                             ipEles = new XElement("iplist");
                    foreach (var whiteList in wlGroup)
                    {
                        switch (wlGroup.Key.ToLower())
                        {
                            case "domain":
                                domainEles.Add(new XElement("url") { Value = whiteList.DomainName });
                                break;
                            case "mac":
                                macEles.Add(new XElement("mac") { Value = whiteList.Mac });
                                break;
                            case "port":
                                {
                                    portEles.Add(new XElement("port")
                                        {
                                            Value =
                                                whiteList.PortEnd.HasValue && whiteList.PortEnd > 0
                                                    ? string.Format("{0}-{1}", whiteList.PortStart, whiteList.PortEnd)
                                                    : whiteList.PortStart.ToString()
                                        });
                                    break;
                                }
                            case "ip":
                                ipEles.Add(new XElement("ip")
                                    {
                                        Value = !string.IsNullOrWhiteSpace(whiteList.IpEnd) && whiteList.IpEnd != "-1"
                                                    ? string.Format("{0}-{1}", whiteList.IpStart, whiteList.IpEnd)
                                                    : whiteList.IpStart
                                    });
                                break;
                        }
                    }
                    if (!domainEles.IsEmpty)
                        wlEle.Add(domainEles);
                    if (!macEles.IsEmpty)
                        wlEle.Add(macEles);
                    if (!portEles.IsEmpty)
                        wlEle.Add(portEles);
                    if (!ipEles.IsEmpty)
                        wlEle.Add(ipEles);
                }
            }
            return wlEle;
        }

        public XElement CreateMonitorSettingElement(MonitorSetting monitorSetting, string[] protocols)
        {
            var msEle = new XElement("monitorparameter");
            if (protocols != null && protocols.Any())
            {
                var protocolEles = new XElement("protocol");
                foreach (string protocol in protocols)
                {
                    protocolEles.Add(new XElement("name") {Value = protocol});
                }
                msEle.Add(protocolEles);
            }
            if (monitorSetting != null)
            {
                var htmlEle = new XElement("html");
                htmlEle.Add(new XAttribute("save", monitorSetting.IsSaveWebContent ? 1 : 0));
                long minSize = monitorSetting.MinSize.HasValue ? monitorSetting.MinSize.Value : 0,
                     maxSize = monitorSetting.MaxSize.HasValue ? monitorSetting.MaxSize.Value : 0;
                htmlEle.Add(new XAttribute("filelen", string.Format("{0}-{1}", minSize, maxSize)));
                htmlEle.Add(new XAttribute("type",
                                           string.IsNullOrWhiteSpace(monitorSetting.SaveFileExts)
                                               ? string.Empty
                                               : monitorSetting.SaveFileExts));
                htmlEle.Add(new XAttribute("autodel", monitorSetting.SaveFileDay));
                msEle.Add(htmlEle);
            }
            return msEle;
        }

        public XElement CreateAlertElement(AlertSetting[] alertSettings)
        {
            var alertEle = new XElement("warnparameter");
            if (alertSettings != null && alertSettings.Any())
            {
                var smsAlertSetting = alertSettings.FirstOrDefault(p => p.AlertType == 1);
                if (smsAlertSetting != null)
                    alertEle.Add(CreateSmsAlertElement(smsAlertSetting));
                var emailAlertSetting = alertSettings.FirstOrDefault(p => p.AlertType == 2);
                if (emailAlertSetting != null)
                    alertEle.Add(CreateEmailAlertElement(emailAlertSetting));
            }
            return alertEle;
        }

        private XElement CreateSmsAlertElement(AlertSetting smsAlertSetting)
        {
            var smsEle = new XElement("sms");
            if (smsAlertSetting != null)
            {
                smsEle.Add(new XAttribute("isopen", smsAlertSetting.StatusToken > 0 ? 1 : 0));
                smsEle.Add(new XAttribute("delay", smsAlertSetting.AlertTimespan));
                smsEle.Add(CreateXAttr("devicetype", smsAlertSetting.DeviceType));
                smsEle.Add(new XAttribute("devicebps", smsAlertSetting.BaudRate));
                smsEle.Add(CreateXAttr("devicecom", smsAlertSetting.SerialPort));
                smsEle.Add(CreateXAttr("phonelist", smsAlertSetting.AlertPhone));
            }
            return smsEle;
        }

        private XElement CreateEmailAlertElement(AlertSetting alertSetting)
        {
            var emailAlertEle = new XElement("mail");
            if (alertSetting != null)
            {
                emailAlertEle.Add(new XAttribute("isopen", alertSetting.StatusToken > 0 ? 1 : 0));
                emailAlertEle.Add(new XAttribute("delay", alertSetting.AlertTimespan));
                emailAlertEle.Add(CreateXAttr("mailfrom", alertSetting.SenderEmail));
                emailAlertEle.Add(CreateXAttr("smtpserver", alertSetting.SmtpServer));
                emailAlertEle.Add(CreateXAttr("user", alertSetting.SmtpAccount));
                emailAlertEle.Add(CreateXAttr("pass", alertSetting.SmtpPassword));
                emailAlertEle.Add(CreateXAttr("maillist", alertSetting.AlertEmail));
            }
            return emailAlertEle;
        }

        public XElement CreateSetAdslElement(MonitorSetting monitorSetting)
        {
            var setAdslEle = new XElement("setadsl");
            if (monitorSetting != null)
            {
                setAdslEle.Add(new XAttribute("data_pvcvci", monitorSetting.DataPVCVCI ?? 0));
                setAdslEle.Add(new XAttribute("data_pvcvpi", monitorSetting.DataPVCVPI ?? 0));
                setAdslEle.Add(new XAttribute("iptv_pvcvci", monitorSetting.IptvPVCVCI ?? 0));
                setAdslEle.Add(new XAttribute("iptv_pvcvpi", monitorSetting.IptvPVCVPI ?? 0));
            }
            return setAdslEle;
        }

        public XElement CreateGetAdslElement(long msId)
        {
            var getAdslEle = new XElement("getadsl", new XAttribute("monitorid", msId));
            return getAdslEle;
        }

        public XElement CreateRmSvrElement(RemoteServer remoteServer)
        {
            var setRmSvrEle = new XElement("rcontrol");
            if (remoteServer != null)
            {
                setRmSvrEle.Add(new XAttribute("enable", remoteServer.StatusToken != 0));
                setRmSvrEle.Add(new XElement("ip", remoteServer.Ip));
                setRmSvrEle.Add(new XElement("port", remoteServer.Port));
                setRmSvrEle.Add(new XElement("user", remoteServer.Username));
                setRmSvrEle.Add(new XElement("passwd", remoteServer.Pass));
            }
            return setRmSvrEle;
        }

        private XAttribute CreateXAttr(string name, string value)
        {
            return new XAttribute(name, string.IsNullOrWhiteSpace(value) ? string.Empty : value);
        }
    }
}